package com.ruoyi.health.report.service.impl;

import com.github.pagehelper.PageHelper;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.enums.AttachmentEnum;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.PrimaryKeyIdUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.bean.JSONUtil;
import com.ruoyi.common.core.utils.file.Base64ToMultipartFile;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.datascope.annotation.DataScope4Health;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.customer.api.RemoteCustomerService;
import com.ruoyi.customer.api.domain.CustomerManagement;
import com.ruoyi.health.api.domain.HealthAnalysisResult;
import com.ruoyi.health.api.enums.ReportEnum;
import com.ruoyi.health.report.api.RemoteGlossoscopyService;
import com.ruoyi.health.report.domain.*;
import com.ruoyi.health.report.domain.zkxc.ZkxcPushBaseEntity;
import com.ruoyi.health.report.domain.zkxc.ZkxcPushDataEntity;
import com.ruoyi.health.report.mapper.HealthAnalysisResultMapper;
import com.ruoyi.health.report.mapper.HealthReportMapper;
import com.ruoyi.health.report.mapper.ZkxcPushDataMapper;
import com.ruoyi.health.report.mapstruct.GlossoscopyMapper;
import com.ruoyi.health.report.service.IHealthReportService;
import com.ruoyi.health.report.service.IHealthZkxcService;
import com.ruoyi.iot.api.RemoteIotService;
import com.ruoyi.iot.api.domain.WatchInfoVO;
import com.ruoyi.mall.api.RemoteMallService;
import com.ruoyi.mall.api.domian.Product;
import com.ruoyi.mall.api.domian.RecommendProductsVO;
import com.ruoyi.system.api.RemoteAttachmentService;
import com.ruoyi.system.api.RemoteFileService;
import com.ruoyi.system.api.RemoteUploadService;
import com.ruoyi.system.api.domain.Attachment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 健康报告Service业务层处理
 * 
 * @author luogongqun
 * @date 2024-09-16
 */
@Service
public class HealthReportServiceImpl implements IHealthReportService 
{
    @Resource
    private HealthReportMapper healthReportMapper;
    @Autowired
    private RemoteGlossoscopyService remoteGlossoscopyService;
    @Autowired
    private RemoteUploadService remoteUploadService;
    @Autowired
    private RemoteAttachmentService remoteAttachmentService;
    @Autowired
    private HealthAnalysisResultMapper healthAnalysisResultMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private RemoteFileService remoteFileService;
    @Autowired
    private RemoteMallService remoteMallService;

    @Autowired
    private RemoteCustomerService remoteCustomerService;

    @Autowired
    private ZkxcPushDataMapper zkxcPushDataMapper;

    @Autowired
    private IHealthZkxcService zkxcService;

    @Autowired
    private RemoteIotService remoteIotService;

    @Value("${glossoscopy.url}")
    private String glossoscopyUrl;
    @Value("${glossoscopy.key}")
    private String key;
    @Value("${glossoscopy.param1}")
    private String param1;
    @Value("${glossoscopy.param2}")
    private String param2;

    /**
     * 查询健康报告
     * 
     * @param id 健康报告主键
     * @return 健康报告
     */
    @Override
    public HealthReport selectHealthReportById(Long id)
    {
        return healthReportMapper.selectHealthReportById(id);
    }

    /**
     * 查询健康报告列表
     * 
     * @param healthReport 健康报告
     * @return 健康报告
     */
    @Override
    public List<HealthReport> selectHealthReportList(HealthReport healthReport)
    {
        return healthReportMapper.selectHealthReportList(healthReport);
    }

    /**
     * 新增健康报告
     * 
     * @param healthReport 健康报告
     * @return 结果
     */
    @Override
    public int insertHealthReport(HealthReport healthReport)
    {
        healthReport.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
        healthReport.setCreateTime(DateUtils.getNowDate());
        return healthReportMapper.insertHealthReport(healthReport);
    }

    /**
     * 修改健康报告
     * 
     * @param healthReport 健康报告
     * @return 结果
     */
    @Override
    public int updateHealthReport(HealthReport healthReport)
    {
        return healthReportMapper.updateHealthReport(healthReport);
    }

    /**
     * 批量删除健康报告
     * 
     * @param ids 需要删除的健康报告主键
     * @return 结果
     */
    @Override
    public int deleteHealthReportByIds(Long[] ids)
    {
        return healthReportMapper.deleteHealthReportByIds(ids);
    }

    /**
     * 删除健康报告信息
     * 
     * @param id 健康报告主键
     * @return 结果
     */
    @Override
    public int deleteHealthReportById(Long id)
    {
        return healthReportMapper.deleteHealthReportById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public GlossoscopyVO glossoscopy(Map<String,String> map) {
        String image = map.get("imgBase64");
        ResponseEntity<GlossoscopyEntity> rResponseEntity = null;
        try {
            Map<String, String> requestParam = new HashMap<>();
            requestParam.put(param2,image.split(",")[1]);
            requestParam.put(param1,key);
            rResponseEntity = restTemplate.postForEntity(glossoscopyUrl, requestParam, GlossoscopyEntity.class);
        } catch (RestClientException e) {
            throw new ServiceException("没检测到人脸",400);
        }
//        R<GlossoscopyVO> result = remoteGlossoscopyService.xushiFaceBase64(map);
        if(rResponseEntity.getStatusCode()!= HttpStatus.OK || Objects.requireNonNull(rResponseEntity.getBody()).getCode()!= com.ruoyi.common.core.constant.HttpStatus.SUCCESS){
            throw new ServiceException("诊断失败，请重试");
        }
        GlossoscopyVO data = rResponseEntity.getBody().getData().getPred();
        //生成健康报告记录
        HealthReport report = new HealthReport();
        report.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
        report.setCustomerId(SecurityUtils.getUserId());
        report.setCustomerName(SecurityUtils.getUsername());
        report.setTsStart(DateUtils.getNowDate());
        report.setTsEnd(DateUtils.getNowDate());
        report.setType(ReportEnum.GLOSSOSCOPY.getCode());
        healthReportMapper.insertHealthReport(report);
        //生成报告设备数据关联数据

        Base64ToMultipartFile file = new Base64ToMultipartFile(image.split(",")[1], "png", "image/png");
//        MultipartFile file = Base64ToMultipartFile.base64Convert(map.get("imgBase64"));

        R<String> upload = remoteUploadService.upload(file);
        if (!Constants.SUCCESS.equals(upload.getCode())){
           throw new ServiceException("文件上传失败");
        }
        Attachment attachment = new Attachment();
        attachment.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
        attachment.setName(file.getName()+".png");
        attachment.setSize(file.getSize());
        attachment.setFileId(upload.getData());
        attachment.setType(AttachmentEnum.PICTURE.getCode());
        attachment.setCreateTime(DateUtils.getNowDate());
        attachment.setAssociatedId(report.getId());
        remoteAttachmentService.add(attachment);
        //保存舌诊的判定结果
        HealthAnalysisResult healthAnalysisResult = new HealthAnalysisResult();

        healthAnalysisResult.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
        healthAnalysisResult.setReportId(report.getId());
        healthAnalysisResult.setResults(JSONUtil.ObjectToJsonNode(data));
        healthAnalysisResult.setCreateTime(DateUtils.getNowDate());
        healthAnalysisResult.setCreateBy(SecurityUtils.getUsername());
        healthAnalysisResult.setType(ReportEnum.GLOSSOSCOPY.getCode());
        healthAnalysisResultMapper.insertHealthAnalysisResult(healthAnalysisResult);

        //获取推荐商品
        String result = Arrays.stream(data.getScore())
                .map(String::valueOf) // 将 Integer 转换为 String
                .reduce((a, b) -> a + "," + b) // 使用逗号连接
                .orElse("");
        GlossoscopyDTO glossoscopyDTO = GlossoscopyMapper.INSTANCE.customerManagemtn2PersonalInfo(data);
        if(StringUtils.isNoneBlank(result)){
            RecommendProductsVO<String> vo = new RecommendProductsVO<>();
            vo.setReportType(ReportEnum.GLOSSOSCOPY);
            vo.setParam(result);
            R<List<Product>> recommendProducts = remoteMallService.getRecommendProducts(vo, SecurityConstants.INNER);
            glossoscopyDTO.setProductList(recommendProducts.getData());
        }

        return glossoscopyDTO;
    }

    @Override
    public HealthAnalysisResult getDetail(Long reportId) {

        HealthAnalysisResult result = healthAnalysisResultMapper.selectHealthAnalysisResultByReportId(reportId);
        RecommendProductsVO<?> queryParam = ReportEnum.getQueryParam(result.getType(), result);
        if(queryParam!=null){
            R<List<Product>> recommendProducts = remoteMallService.getRecommendProducts(queryParam, SecurityConstants.INNER);
            result.setProductList(recommendProducts.getData());
        }
        return result;
    }


    @DataScope4Health(alias = "h")
    @Override
    public List<HealthReport> selectWxHealthReportList(HealthReport healthReport) {
        return healthReportMapper.selectHealthReportList(healthReport);
    }

    @Override
    public HealthAnalysisVO getLastReportInfo(Long customerId) {
        HealthReport lastSzReport = healthReportMapper.getLastSzReport(customerId);
        if(lastSzReport!=null){
            HealthAnalysisVO vo = zkxcService.getZkxcReportByReportId(lastSzReport.getId());
            return vo;
        }
        return null;
    }

    @Override
    @Transactional
    public void getLastReportInfoByMock(String phone) {
        Long customerId = null;
        if(StringUtils.isNotBlank( phone)){
            R<CustomerManagement> phoneNumber = remoteCustomerService.getInfoByPhoneNumber(phone, SecurityConstants.INNER);
            if (!StringUtils.isNull(phoneNumber) && !StringUtils.isNull(phoneNumber.getData())){
                customerId = phoneNumber.getData().getId();
            }
        }
        HealthReport lastSzReport = healthReportMapper.selectHealthReportById(608380828002557952L);
        ZkxcPushDataEntity zkxcPushDataEntity = zkxcPushDataMapper.selectZkxcPushDataByReportId(lastSzReport.getId());
        lastSzReport.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
        lastSzReport.setCreateTime(DateUtils.getNowDate());
        lastSzReport.setCustomerId(customerId);
        healthReportMapper.insertHealthReport(lastSzReport);
        zkxcPushDataEntity.setId(PrimaryKeyIdUtils.getSysIdWorker().nextId());
        zkxcPushDataEntity.setHealthReportId(lastSzReport.getId());
        zkxcPushDataEntity.setReqTime(DateUtils.getNowDate());
        zkxcPushDataEntity.setCustomerId(customerId);
        zkxcPushDataMapper.insertZkxcPushDataEntity(zkxcPushDataEntity);
        remoteIotService.addmockData(customerId, SecurityConstants.INNER);
    }

    @Override
    public DiagnosisData  getLastReportInfoByDate(String phone, String date,boolean watch) {
        DiagnosisData diagnosisData = new DiagnosisData();
        Long customerId = null;
        if(StringUtils.isNotBlank( phone)){
            R<CustomerManagement> phoneNumber = remoteCustomerService.getInfoByPhoneNumber(phone, SecurityConstants.INNER);
            if (StringUtils.isNull(phoneNumber) || StringUtils.isNull(phoneNumber.getData())){
                return diagnosisData;
            }
            customerId = phoneNumber.getData().getId();
            if(phoneNumber.getData().getSex()!=null){
                diagnosisData.setSex("1".equals(phoneNumber.getData().getSex())?"女":"男");
            }
            Date birthDate = phoneNumber.getData().getBirthDate();
            if (birthDate != null) {
                long ageInMillis = new Date().getTime() - birthDate.getTime();
                int age = (int) (ageInMillis / (1000L * 60 * 60 * 24 * 365));
                diagnosisData.setAge(age);
            }
            diagnosisData.setWeight(phoneNumber.getData().getWeight());
            diagnosisData.setHeight(phoneNumber.getData().getHeight());
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");
        Date date1 = null;
        try {
            date1 = sdf.parse(date);
        } catch (ParseException e) {
            return diagnosisData;
        }
        HealthReport lastSzReport = healthReportMapper.getLastSzReportByDate(customerId,date1);
        if(lastSzReport == null){
            return diagnosisData;
        }
        if(StringUtils.isBlank( phone)){
            R<CustomerManagement> phoneNumber = remoteCustomerService.getInfoById(lastSzReport.getCustomerId(), SecurityConstants.INNER);
            if (StringUtils.isNull(phoneNumber) || StringUtils.isNull(phoneNumber.getData())){
                return diagnosisData;
            }
            if(phoneNumber.getData().getSex()!=null){
                diagnosisData.setSex("1".equals(phoneNumber.getData().getSex())?"女":"男");
            }
            Date birthDate = phoneNumber.getData().getBirthDate();
            if (birthDate != null) {
                long ageInMillis = new Date().getTime() - birthDate.getTime();
                int age = (int) (ageInMillis / (1000L * 60 * 60 * 24 * 365));
                diagnosisData.setAge(age);
            }
            diagnosisData.setWeight(phoneNumber.getData().getWeight());
            diagnosisData.setHeight(phoneNumber.getData().getHeight());
        }
        HealthAnalysisVO vo = zkxcService.getZkxcReportByReportId(lastSzReport.getId());
        if(vo==null){
            return diagnosisData;
        }
        ZkxcPushBaseEntity baseEntity = vo.getBaseEntity();
        if(baseEntity.getMzPushEntity() != null){
            DiagnosisData.Pulse pulseLeft = new DiagnosisData.Pulse();
            diagnosisData.setPulseLeft(pulseLeft);
            pulseLeft.setChi(baseEntity.getMzPushEntity().getLeftChi().getPulsePotential());
            pulseLeft.setGuan(baseEntity.getMzPushEntity().getLeftGuan().getPulsePotential());
            pulseLeft.setCun(baseEntity.getMzPushEntity().getLeftCun().getPulsePotential());
            DiagnosisData.Pulse pulseRight = new DiagnosisData.Pulse();
            diagnosisData.setPulseRight(pulseRight);
            pulseRight.setCun(baseEntity.getMzPushEntity().getRightCun().getPulsePotential());
            pulseRight.setGuan(baseEntity.getMzPushEntity().getRightGuan().getPulsePotential());
            pulseRight.setChi(baseEntity.getMzPushEntity().getRightChi().getPulsePotential());
        }

        if(baseEntity.getSzPushEntity()!=null){
            DiagnosisData.Tongue tongue = new DiagnosisData.Tongue();
            diagnosisData.setTongue(tongue);
            tongue.setColor(baseEntity.getSzPushEntity().getLZhiStr());
            tongue.setShape(baseEntity.getSzPushEntity().getPsStr());
            tongue.setMoisture(baseEntity.getSzPushEntity().getLnStr());
            tongue.setCoatingColor(baseEntity.getSzPushEntity().getLCoatStr());
            tongue.setCoatingThickness(baseEntity.getSzPushEntity().getHbStr());
            tongue.setCoatingTexture(baseEntity.getSzPushEntity().getFnStr());
            String spotsthorn = baseEntity.getSzPushEntity().getSpotsthorn();
            Double spotsthornInt = Double.parseDouble(spotsthorn);
            String spotsthornStr=spotsthornInt<1?"无点刺":"有点刺";
            tongue.setOtherFeatures(baseEntity.getSzPushEntity().getTeethmark()+","+baseEntity.getSzPushEntity().getCrackStr()+","+spotsthornStr);
        }
         if(watch){
            R<WatchInfoVO> ajaxResult = remoteIotService.getLastMessageByCustomerIdDate(customerId,date,SecurityConstants.INNER);
            if (StringUtils.isNotNull(ajaxResult) && StringUtils.isNotNull(ajaxResult.getData())){
                WatchInfoVO watchInfoVO =ajaxResult.getData();
                if(watchInfoVO.getHeartRate() == null){
                    return new DiagnosisData();
                }
                diagnosisData.setHealthIndicators(watchInfoVO);
            }else {
                return new DiagnosisData();
            }
        }
        return diagnosisData;
    }

}
